package com.master.demo.controller.generator;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.master.demo.framework.base.BaseController;
import com.master.demo.generator.config.GenConstants;
import com.master.demo.generator.pojo.command.GenTableQry;
import com.master.demo.generator.pojo.entity.GenTable;
import com.master.demo.generator.pojo.entity.GenTableColumn;
import com.master.demo.generator.service.IGenTableColumnService;
import com.master.demo.generator.service.IGenTableService;
import com.master.demo.sys.constant.SysLogTypeConstant;
import com.master.common.annotation.Log;
import com.master.common.api.ResponseInfo;
import com.master.common.enums.BusinessTypeEnum;
import com.master.common.exception.ErrorException;
import com.master.common.validator.ValidatorUtil;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 代码生成接口
 *
 * @author: Yang
 * @date: 2023/01/31
 * @version: 1.0.0
 * https://www.panday94.xyz
 * Copyright Ⓒ 2023 熊扬软件开发工作室 Limited All rights reserved.
 */
@RestController
@RequestMapping("/generator")
public class GenController extends BaseController {
    @Autowired
    private IGenTableService genTableService;
    @Autowired
    private IGenTableColumnService genTableColumnService;

    /**
     * 查询代码生成列表
     *
     * @author: Yang
     * @date: 2023/01/31
     * @version: 1.0.0
     */
    @GetMapping("/table/gen/page")
    @PreAuthorize("hasAuthority('tool:gen:list')")
    public ResponseInfo pageGenTable(GenTableQry query) {
        query.assertPage();
        return genTableService.pageGenTable(query);
    }

    /**
     * 查询数据库列表
     *
     * @author: Yang
     * @date: 2023/01/31
     * @version: 1.0.0
     */
    @GetMapping("/table/db/page")
    @PreAuthorize("hasAuthority('tool:gen:list')")
    public ResponseInfo pageDbTable(GenTableQry query) {
        query.assertPage();
        return genTableService.pageDbTable(query);
    }

    /**
     * 获取代码生成信息
     *
     * @author: Yang
     * @date: 2023/01/31
     * @version: 1.0.0
     */
    @GetMapping(value = "/table/{tableId}")
    @PreAuthorize("hasAuthority('tool:gen:query')")
    public ResponseInfo getInfo(@PathVariable Long tableId) {
        GenTable info = genTableService.getGenTableById(tableId);
        List<GenTable> tables = genTableService.listGenTable();
        List<GenTableColumn> rows = genTableColumnService.listGenTableColumnByTableId(tableId);
        Map<String, Object> map = new HashMap<>(16);
        map.put("info", info);
        map.put("tables", tables);
        map.put("rows", rows);
        return ResponseInfo.success(map);
    }

    /**
     * 查询数据表字段列表
     *
     * @author: Yang
     * @date: 2023/01/31
     * @version: 1.0.0
     */
    @GetMapping(value = "/table/columns/{tableId}")
    @PreAuthorize("hasAuthority('tool:gen:query')")
    public ResponseInfo columnList(Long tableId) {
        List<GenTableColumn> list = genTableColumnService.listGenTableColumnByTableId(tableId);
        return ResponseInfo.success(list);
    }

    /**
     * 导入表结构
     *
     * @author: Yang
     * @date: 2023/01/31
     * @version: 1.0.0
     */
    @PostMapping("/table/import")
    @PreAuthorize("hasAuthority('tool:gen:import')")
    @Log(type = SysLogTypeConstant.GEN_CODE, businessType = BusinessTypeEnum.IMPORT)
    public ResponseInfo importTableSave(String tables) {
        genTableService.importGenTable(Convert.toStrArray(tables), getSysUserName());
        return ResponseInfo.success();
    }

    /**
     * 修改代码生成规则
     *
     * @author: Yang
     * @date: 2023/01/31
     * @version: 1.0.0
     */
    @PutMapping("/table")
    @PreAuthorize("hasAuthority('tool:gen:update')")
    @Log(type = SysLogTypeConstant.GEN_CODE, businessType = BusinessTypeEnum.UPDATE)
    public ResponseInfo editSave(@Validated @RequestBody GenTable genTable) {
        validateEdit(genTable);
        genTableService.updateGenTable(genTable, getLoginUser().getUsername());
        return ResponseInfo.success();
    }

    /**
     * 删除代码生成
     *
     * @author: Yang
     * @date: 2023/01/31
     * @version: 1.0.0
     */
    @DeleteMapping("/table/{tableIds}")
    @PreAuthorize("hasAuthority('tool:gen:remove')")
    @Log(type = SysLogTypeConstant.GEN_CODE, businessType = BusinessTypeEnum.DELETE)
    public ResponseInfo remove(@PathVariable List<Long> tableIds) {
        genTableService.deleteGenTableByIds(tableIds);
        return ResponseInfo.success();
    }

    /**
     * 预览代码
     *
     * @author: Yang
     * @date: 2023/01/31
     * @version: 1.0.0
     */
    @GetMapping("/table/preview/{tableId}")
    @PreAuthorize("hasAuthority('tool:gen:preview')")
    public ResponseInfo preview(@PathVariable("tableId") Long tableId) {
        return ResponseInfo.success(genTableService.previewCode(tableId));
    }

    /**
     * 生成代码（下载方式）
     *
     * @author: Yang
     * @date: 2023/01/31
     * @version: 1.0.0
     */
    @GetMapping("/table/download/{tableName}")
    @PreAuthorize("hasAuthority('tool:gen:code')")
    @Log(value = "生成代码（下载方式）", type = SysLogTypeConstant.GEN_CODE, businessType = BusinessTypeEnum.GENCODE)
    public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException {
        byte[] data = genTableService.downloadCode(tableName);
        genCode(response, data);
    }

    /**
     * 批量生成代码
     *
     * @author: Yang
     * @date: 2023/01/31
     * @version: 1.0.0
     */
    @GetMapping("/table/download/batch")
    @PreAuthorize("hasAuthority('tool:gen:code')")
    @Log(value = "批量生成代码（下载方式）", type = SysLogTypeConstant.GEN_CODE, businessType = BusinessTypeEnum.GENCODE)
    public void batchGenCode(HttpServletResponse response, String tables) throws IOException {
        String[] tableNames = Convert.toStrArray(tables);
        byte[] data = genTableService.downloadCode(tableNames);
        genCode(response, data);
    }

    /**
     * 生成代码（自定义路径）
     *
     * @author: Yang
     * @date: 2023/01/31
     * @version: 1.0.0
     */
    @GetMapping("/table/code/{tableName}")
    @PreAuthorize("hasAuthority('tool:gen:code')")
    @Log(value = "生成代码", type = SysLogTypeConstant.GEN_CODE, businessType = BusinessTypeEnum.GENCODE)
    public ResponseInfo genCode(@PathVariable("tableName") String tableName) {
        genTableService.generatorCode(tableName);
        return ResponseInfo.success();
    }

    /**
     * 同步数据库
     *
     * @author: Yang
     * @date: 2023/01/31
     * @version: 1.0.0
     */
    @GetMapping("/db/synch/{tableName}")
    @Log(value = "同步数据库", type = SysLogTypeConstant.GEN_CODE, businessType = BusinessTypeEnum.UPDATE)
    public ResponseInfo synchDb(@PathVariable("tableName") String tableName) {
        genTableService.synchDb(tableName, getLoginUser().getUsername());
        return ResponseInfo.success();
    }

    /**
     * 生成zip文件
     */
    private void genCode(HttpServletResponse response, byte[] data) throws IOException {
        response.reset();
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Content-Disposition", "attachment; filename=\"hxiang.zip\"");
        response.addHeader("Content-Length", "" + data.length);
        response.setContentType("application/octet-stream; charset=UTF-8");
        IOUtils.write(data, response.getOutputStream());
    }

    /**
     * 修改保存参数校验
     *
     * @param genTable 业务信息
     */
    public void validateEdit(GenTable genTable) {
        if (GenConstants.TPL_TREE.equals(genTable.getTplCategory())) {
            String options = JSON.toJSONString(genTable.getParams());
            JSONObject paramsObj = JSON.parseObject(options);
            if (ValidatorUtil.isNull(paramsObj.getString(GenConstants.TREE_CODE))) {
                throw new ErrorException("树编码字段不能为空");
            } else if (ValidatorUtil.isNull(paramsObj.getString(GenConstants.TREE_PARENT_CODE))) {
                throw new ErrorException("树父编码字段不能为空");
            } else if (ValidatorUtil.isNull(paramsObj.getString(GenConstants.TREE_NAME))) {
                throw new ErrorException("树名称字段不能为空");
            } else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory())) {
                if (ValidatorUtil.isNull(genTable.getSubTableName())) {
                    throw new ErrorException("关联子表的表名不能为空");
                } else if (ValidatorUtil.isNull(genTable.getSubTableFkName())) {
                    throw new ErrorException("子表关联的外键名不能为空");
                }
            }
        }
    }

}